/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.ibm.staf.STAFException;
import com.ibm.staf.STAFHandle;
import com.ibm.staf.STAFMarshallingContext;
import com.ibm.staf.STAFResult;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author think
 */
@Singleton
public class STAFHelper {

    STAFHandle handle;
    ConfigManager configManager;

    @Inject
    public STAFHelper(ConfigManager configManager) {
        this.configManager = configManager;
    }

    public boolean isMachineAlive(String machine) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(machine, "ping", "ping");
            handle.unRegister();
            if (result.rc == 0) {
                return true;
            }
        } catch (STAFException ex) {
//            Logger.getLogger(VMMachine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    public boolean startMachine(String machine, String hostMachine, String vmFileName) {
        if (!isMachineAlive(machine)) {
            try {
                handle = new STAFHandle(configManager.startVMHandleName());
                STAFResult result = handle.submit2(hostMachine, "process", "start command \"vmrun start " +
                        "\\\"" + vmFileName.replace("\\", "\\\\") + "\\\"\" stderrtostdout returnstdout wait");
                handle.unRegister();
                if (result.rc == 0) {
                    if (STAFMarshallingContext.isMarshalledData(result.result)) {
                        STAFMarshallingContext mc = STAFMarshallingContext.unmarshall(
                                result.result);
                        HashMap hash = (HashMap) mc.getRootObject();
                        HashMap item = (HashMap) ((LinkedList) hash.get("fileList")).get(0);
                        if (!item.get("data").toString().startsWith("Error")) {
                            while (true) {
                                if (this.isMachineAlive(machine)) {
//                                if (isStarted() && setUpSTAFVars()) {
                                    return true;
                                } else {
                                    Thread.sleep(500);
//                                    Logger.getLogger("Wait for VMMachine to start up...");
                                    System.out.println("Wait for VMMachine to start up...");
                                }
                            }
                        }
                    }
                } else {
                    System.out.println(result.result);
                }
            } catch (Exception ex) {

                Logger.getLogger(VMMachine.class.getName()).log(Level.SEVERE, null, ex);
            }
            return false;
        } else {
            return true;
        }
    }

    public boolean setupSTAFVars(String machine, String key, String value) {
        try {
            handle = new STAFHandle("set_var");
            STAFResult result = handle.submit2(machine, "var", "set shared var " + key + "=" + value);
//            STAFResult result = handle.submit2(machine, "var", "set shared var INTMONITOR/INSTALLER_PATH=" + installerPath);
            if (result.rc == 0) {
                return true;
            } else {
                System.out.println(result.result);
            }
        } catch (STAFException e) {
            e.printStackTrace();
        }
        return false;

    }

    public boolean revertToSnapshot(String machine, String vmFileName, String snapshotName) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(machine, "process", "start command \"vmrun revertToSnapshot " +
                    "\\\"" + vmFileName.replace("\\", "\\\\") + "\\\" " + snapshotName +
                    " \" stderrtostdout returnstdout wait");
            System.out.println("start command \"vmrun revertToSnapshot " +
                    "\\\"" + vmFileName.replace("\\", "\\\\") + "\\\" " + snapshotName +
                    " \" stderrtostdout returnstdout wait");
            handle.unRegister();
            if (result.rc == 0) {
                if (STAFMarshallingContext.isMarshalledData(result.result)) {
                    STAFMarshallingContext mc = STAFMarshallingContext.unmarshall(
                            result.result);
                    HashMap hash = (HashMap) mc.getRootObject();
                    HashMap item = (HashMap) ((LinkedList) hash.get("fileList")).get(0);
                    System.out.println(item.get("data").toString());
                    if (item.get("data").toString().startsWith("Error")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            } else {
                System.out.println(result.result);
            }

        } catch (STAFException ex) {
            Logger.getLogger(VMMachine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    public boolean stopMachine(String machine) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(machine, "process", "start command \"shutdown -s -f -t 0\"");
            handle.unRegister();
            if (result.rc == 0) {
                try {
                    Thread.sleep(120000);
                } catch (InterruptedException ex) {
                    Logger.getLogger(VMMachine.class.getName()).log(Level.SEVERE, null, ex);
                }
                return true;
            }
        } catch (STAFException ex) {
            System.out.println(ex.getMessage());
        }
        return false;
    }

    public boolean takeSnapshot(String machine, String vmFileName, String snapshotName) {
        try {
            handle = new STAFHandle(configManager.getTakeSnapshotHandleName());
            STAFResult result = handle.submit2(machine, "process", "start command " +
                    " \"vmrun snapshot \\\"" + vmFileName.replace("\\", "\\\\") + "\\\" " + snapshotName + "\" stderrtostdout returnstdout wait");
            handle.unRegister();
            if (result.rc == 0) {
                if (STAFMarshallingContext.isMarshalledData(result.result)) {
                    STAFMarshallingContext mc = STAFMarshallingContext.unmarshall(
                            result.result);
                    HashMap hash = (HashMap) mc.getRootObject();
                    HashMap item = (HashMap) ((LinkedList) hash.get("fileList")).get(0);
                    if (item.get("data").toString().startsWith("Error")) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        } catch (STAFException ex) {
            Logger.getLogger(VMMachine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    public boolean copyFile(String sourceMachine, String sourceFile, String targetMachine, String targetFile) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(sourceMachine, "fs", "copy file \"" + sourceFile.replace("\\", "\\\\") +
                    "\" tomachine " + targetMachine + " tofile \"" + targetFile.replace("\\", "\\\\") + "\"");
            handle.unRegister();
            if (result.rc == 0) {
                return true;
            } else {
                System.out.println(result.result);
            }
        } catch (STAFException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean copyDirectory(String sourceMachine, String sourceDir, String targetMachine, String targetDir) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(sourceMachine, "fs", "copy directory \"" + sourceDir.replace("\\", "\\\\") +
                    "\" tomachine " + targetMachine + " todirectory \"" + targetDir.replace("\\", "\\\\") + "\" recurse");
            handle.unRegister();
            if (result.rc == 0) {
                return true;
            } else {
                System.out.println(result.result);
            }
        } catch (STAFException e) {
        }
        return false;
    }

    public boolean unzip(String machine, String zipFile, String extractTo) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(machine, "zip", "unzip zipfile \"" + zipFile.replace("\\", "\\\\") +
                    "\" todirectory \"" + extractTo.replace("\\", "\\\\") + "\" replace");
            handle.unRegister();
            if (result.rc == 0) {
                return true;
            } else {
                System.out.println(result.result);
            }
        } catch (STAFException e) {
        }
        return false;
    }

    public boolean deleteFile(String machine, String file) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(machine, "fs", "delete entry \"" + file.replace("\\", "\\\\") + "\" confirm");
            handle.unRegister();
            if (result.rc == 0) {
                return true;
            } else {
                System.out.println(result.result);
            }
        } catch (STAFException e) {
        }
        return false;
    }

    public boolean zip(String machine, String zipFile, String dirToZip, String relativePath) {
        try {
            handle = new STAFHandle("");
            STAFResult result = handle.submit2(machine, "zip", "add zipfile " + "\"" + zipFile.replace("\\", "/") +
                    "\" directory \"" + dirToZip.replace("\\", "/") + "\" relativeto \"" + relativePath.replace("\\", "/") + "\" recurse");
            handle.unRegister();
            if (result.rc == 0) {
                return true;
            } else {
                System.out.println(result.result);
            }
        } catch (STAFException ex) {
            Logger.getLogger(VMMachine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }
}
